using System;
using System.Collections.Generic;
using Audio;
using UnityEngine;
using AudioType = Framework.Audio.AudioType;

/// <summary>
/// 单独分离的音频资源加载器，方便后续升级资源加载策略
/// </summary>
public class AudioSourceHandler : IAudioSourceHandler
{

    private static readonly Dictionary<AudioType, string> _AUDIO_PATH = new Dictionary<AudioType, string>()
                                                                            {
                                                                                {AudioType.BGM, "BGM"},
                                                                                {AudioType.BSE, "BSE"},
                                                                                {AudioType.SOUND, "SE"}
                                                                            };

    private string _audioSourcePath;

    private Dictionary<string, AudioClip> _audioSource;
    private Dictionary<string, int> _audioReferenceCount;

    //用于编辑器状态下监视资源状态
    public Dictionary<string, string> editorLog;
    public Dictionary<string, string> EditorLog() => editorLog;

    private string AudioFullPath(AudioType audioType, string audioName)
    {
        audioName = audioName.Replace("\\", "/");
        return $"{this._audioSourcePath}/{_AUDIO_PATH[audioType]}/{audioName}";
    }


    public AudioSourceHandler(string audioSourcePath)
    {
        this._audioSourcePath = audioSourcePath;
        this._audioReferenceCount = new Dictionary<string, int>();
        this._audioSource = new Dictionary<string, AudioClip>();
#if UNITY_EDITOR
        this.editorLog = new Dictionary<string, string>();
#endif
    }


    /// <summary>
    /// 获取一个音频资源
    /// </summary>
    /// <param name="audioType"></param>
    /// <param name="audioName"></param>
    /// <returns></returns>
    public AudioClip GetAudioClip(ushort audioType, string audioName)
    {
        var audioKey = audioType + audioName;
        //当指定音效没有或者其资源为null时，通过ab包加载
        if (!this._audioSource.ContainsKey(audioKey) || this._audioSource[audioKey] == null)
        {
            this._audioSource[audioKey] = Resources.Load<AudioClip>(this.AudioFullPath((AudioType)audioType, audioName));
            this._audioReferenceCount[audioKey] = 0;
        }

        var audioClip = this._audioSource[audioKey];
        this._audioReferenceCount[audioKey] += audioClip != null ? 1 : 0;
#if UNITY_EDITOR
        this.RefreshLog();
#endif
        return audioClip;
    }

    public void OnAudioInvalid(ushort audioGroup, string audioName)
    {
        var audioKey = audioGroup + audioName;
        if (this._audioReferenceCount.ContainsKey(audioKey) && this._audioReferenceCount[audioKey] >= 1)
        {
            this._audioReferenceCount[audioKey] -= 1;
            if (this._audioReferenceCount[audioKey] == 0)
            {
                if (audioGroup == 0 || audioGroup == 1)
                {
                    var clip = this._audioSource[audioKey];
                    this._audioSource[audioKey] = null;
                    Resources.UnloadAsset(clip);
                }
#if UNITY_EDITOR
                this.RefreshLog();
#endif
            }
        }
    }

    /// <summary>
    /// 卸载所有未使用的音效资源
    /// </summary>
    public void UnLoadAllInvalid()
    {
        List<string> sourceKeys = new List<string>(this._audioSource.Keys);
        for (int i = sourceKeys.Count - 1; i >= 0; i--)
        {
            var audioSourceKey = sourceKeys[i];
            if (this._audioReferenceCount[audioSourceKey] == 0)
            {
                // ushort group = ushort.Parse(audioSourceKey.Substring(0, 1));
                // string audioName = audioSourceKey.Substring(1);
                var clip = this._audioSource[audioSourceKey];
                Resources.UnloadAsset(clip);

                this._audioSource.Remove(audioSourceKey);
                this._audioReferenceCount.Remove(audioSourceKey);
#if UNITY_EDITOR
                this.editorLog.Remove(audioSourceKey);
#endif
            }
        }
#if UNITY_EDITOR
        this.RefreshLog();
#endif
    }


    public void RefreshLog()
    {
#if UNITY_EDITOR
        foreach (var audioSourceKey in this._audioSource.Keys)
        {
            this.editorLog[audioSourceKey] = $"\t{this._audioSource[audioSourceKey] != null} \t{this._audioReferenceCount[audioSourceKey]}";
        }
#endif
    }

    public float[] LoadVolume()
    {
        var volumes = new float[3] { 1,1,1 };
        volumes[0] = Account.Instance.SettingData.BGMValue;
        volumes[1] = Account.Instance.SettingData.BSEValue;
        volumes[2] = Account.Instance.SettingData.SEValue;
        return volumes;
    }

    public void SaveVolume(float bgm, float bse, float se)
    {
        Account.Instance.SettingData.BGMValue = bgm;
        Account.Instance.SettingData.BSEValue = bse;
        Account.Instance.SettingData.SEValue  = se;
        Account.Instance.Save(Framework.Save.SaveData.GameSetting);
    }
}